﻿using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;


namespace luozhuang.Commons
{
    /**/
    /// <summary>
    /// CRC 效验
    /// 快速检测算法
    /// </summary>
    public class CRC32
    {

        protected ulong[] crc32Table;

        /**/
        /// <summary>
        /// 构造：初始化效验表
        /// </summary>
        public CRC32()
        {
            const ulong ulPolynomial = 0xEDB88320;
            ulong dwCrc;
            crc32Table = new ulong[256];
            int i, j;
            for (i = 0; i < 256; i++)
            {
                dwCrc = (ulong)i;
                for (j = 8; j > 0; j--)
                {
                    if ((dwCrc & 1) == 1)
                        dwCrc = (dwCrc >> 1) ^ ulPolynomial;
                    else
                        dwCrc >>= 1;
                }
                crc32Table[i] = dwCrc;
            }
        }

        /**/
        /// <summary>
        /// 字节数组效验
        /// </summary>
        /// <param name="buffer">ref 字节数组</param>
        /// <returns></returns>
        public ulong ByteCRC(ref byte[] buffer)
        {
            ulong ulCRC = 0xffffffff;
            ulong len;
            len = (ulong)buffer.Length;
            for (ulong buffptr = 0; buffptr < len; buffptr++)
            {
                ulong tabPtr = ulCRC & 0xFF;
                tabPtr = tabPtr ^ buffer[buffptr];
                ulCRC = ulCRC >> 8;
                ulCRC = ulCRC ^ crc32Table[tabPtr];
            }
            return ulCRC ^ 0xffffffff;
        }


        /**/
        /// <summary>
        /// 字符串效验
        /// </summary>
        /// <param name="sInputString">字符串</param>
        /// <returns></returns>
        public ulong StringCRC(string sInputString)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(sInputString);
            return ByteCRC(ref buffer);
        }

        /**/
        /// <summary>
        /// 文件效验
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <returns></returns>
        public ulong FileCRC(string sInputFilename)
        {
            FileStream inFile = new System.IO.FileStream(sInputFilename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            byte[] bInput = new byte[inFile.Length];
            inFile.Read(bInput, 0, bInput.Length);
            inFile.Close();

            return ByteCRC(ref bInput);
        }

    }
    /**/
    /// <summary>
    /// SHA256 无逆向编码
    /// 获取唯一特征串，可用于密码加密
    /// (无法还原)
    /// </summary>
    public class SHA256
    {

        public SHA256()
        {
        }

        /**/
        /// <summary>
        /// 获取字符串的特征串
        /// </summary>
        /// <param name="sInputString">输入文本</param>
        /// <returns></returns>
        public string HashString(string sInputString)
        {
            System.Security.Cryptography.SHA256Managed md5 = new System.Security.Cryptography.SHA256Managed();
            string encoded = BitConverter.ToString(md5.ComputeHash(Encoding.UTF8.GetBytes(sInputString))).Replace("-", "");
            return encoded;
        }

        /**/
        /// <summary>
        /// 获取文件的特征串
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <returns></returns>
        public string HashFile(string sInputFilename)
        {
            System.Security.Cryptography.SHA256Managed md5 = new System.Security.Cryptography.SHA256Managed();
          
            FileStream inFile = new System.IO.FileStream(sInputFilename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
            byte[] bInput = new byte[inFile.Length];
            inFile.Read(bInput, 0, bInput.Length);
            inFile.Close();

            string encoded = BitConverter.ToString(md5.ComputeHash(bInput)).Replace("-", "");
            return encoded;
        }

    }

    /**/
    /// <summary>
    /// Base64 UUEncoded 编码
    /// 将二进制编码为ASCII文本，用于网络传输
    /// (可还原)
    /// </summary>
    public class BASE64
    {
        UTF8Encoding utf8 = new UTF8Encoding();

        public BASE64()
        {
        }

        /**/
        /// <summary>
        /// 解码字符串
        /// </summary>
        /// <param name="sInputString">输入文本</param>
        /// <returns></returns>
        public string DecryptString(string sInputString)
        {
            char[] sInput = sInputString.ToCharArray();
            try
            {
                byte[] bOutput = System.Convert.FromBase64String(sInputString);
                return utf8.GetString(bOutput, 0, bOutput.Length);
            }
            catch (System.ArgumentNullException)
            {
                //base 64 字符数组为null
                return "";
            }
            catch (System.FormatException)
            {
                //长度错误，无法整除4
                return "";
            }
        }

        /**/
        /// <summary>
        /// 编码字符串
        /// </summary>
        /// <param name="sInputString">输入文本</param>
        /// <returns></returns>
        public string EncryptString(string sInputString)
        {
            byte[] bInput = Encoding.UTF8.GetBytes(sInputString);
            try
            {
                return System.Convert.ToBase64String(bInput, 0, bInput.Length);
            }
            catch (System.ArgumentNullException)
            {
                //二进制数组为NULL.
                return "";
            }
            catch (System.ArgumentOutOfRangeException)
            {
                //长度不够
                return "";
            }
        }

        /**/
        /// <summary>
        /// 解码文件
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <param name="sOutputFilename">输出文件</param>
        public void DecryptFile(string sInputFilename, string sOutputFilename)
        {
            System.IO.StreamReader inFile;
            char[] base64CharArray;

            try
            {
                inFile = new System.IO.StreamReader(sInputFilename,
                  System.Text.Encoding.UTF8);
                base64CharArray = new char[inFile.BaseStream.Length];
                inFile.Read(base64CharArray, 0, (int)inFile.BaseStream.Length);
                inFile.Close();
            }
            catch
            {//(System.Exception exp) {
                return;
            }

            // 转换Base64 UUEncoded为二进制输出
            byte[] binaryData;
            try
            {
                binaryData =
                  System.Convert.FromBase64CharArray(base64CharArray,
                  0,
                  base64CharArray.Length);
            }
            catch (System.ArgumentNullException)
            {
                //base 64 字符数组为null
                return;
            }
            catch (System.FormatException)
            {
                //长度错误，无法整除4
                return;
            }

            // 写输出数据
            System.IO.FileStream outFile;
            try
            {
                outFile = new System.IO.FileStream(sOutputFilename,
                  System.IO.FileMode.Create,
                  System.IO.FileAccess.Write);
                outFile.Write(binaryData, 0, binaryData.Length);
                outFile.Close();
            }
            catch
            {// (System.Exception exp) {
                //流错误
            }

        }

        /**/
        /// <summary>
        /// 编码文件
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <param name="sOutputFilename">输出文件</param>
        public void EncryptFile(string sInputFilename, string sOutputFilename)
        {

            System.IO.FileStream inFile;
            byte[] binaryData;

            try
            {
                inFile = new System.IO.FileStream(sInputFilename,
                  System.IO.FileMode.Open,
                  System.IO.FileAccess.Read);
                binaryData = new Byte[inFile.Length];
                long bytesRead = inFile.Read(binaryData, 0,
                  (int)inFile.Length);
                inFile.Close();
            }
            catch
            { //(System.Exception exp) {
                return;
            }

            // 转换二进制输入为Base64 UUEncoded输出
            // 每3个字节在源数据里作为4个字节
            long arrayLength = (long)((4.0d / 3.0d) * binaryData.Length);

            // 如果无法整除4
            if (arrayLength % 4 != 0)
            {
                arrayLength += 4 - arrayLength % 4;
            }

            char[] base64CharArray = new char[arrayLength];
            try
            {
                System.Convert.ToBase64CharArray(binaryData,
                  0,
                  binaryData.Length,
                  base64CharArray,
                  0);
            }
            catch (System.ArgumentNullException)
            {
                //二进制数组为NULL.
                return;
            }
            catch (System.ArgumentOutOfRangeException)
            {
                //长度不够
                return;
            }

            // 写UUEncoded数据到文件内
            System.IO.StreamWriter outFile;
            try
            {
                outFile = new System.IO.StreamWriter(sOutputFilename,
                  false,
                  System.Text.Encoding.UTF8);
                outFile.Write(base64CharArray);
                outFile.Close();
            }
            catch
            {// (System.Exception exp) {
                //文件流出错
            }


        }
    }
    /**/
    /// <summary>
    /// DES 加密
    /// 支持Key(钥匙)加密变化
    /// 支持还原
    ///
    /// 演示操作：
    ///  // 64位，8个字节
    ///  string sSecretKey;
    ///
    ///  // 获取Key
    ///  sSecretKey = GenerateKey();
    ///
    ///  // 托管
    ///  GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );
    ///
    ///  // 加密文件
    ///  EncryptFile(@"C:\MyData.txt",
    ///  @"C:\Encrypted.txt",
    ///  sSecretKey);
    ///
    ///  // 解密文件
    ///  DecryptFile(@"C:\Encrypted.txt",
    ///  @"C:\Decrypted.txt",
    ///  sSecretKey);
    ///
    ///  // 释放托管内容
    ///  ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
    ///  gch.Free();
    /// </summary>
    public class DES
    {


        UTF8Encoding utf8 = new UTF8Encoding();

        public DES()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }

        /**/
        /// <summary>
        /// 创建Key
        /// </summary>
        /// <returns></returns>
        public string GenerateKey()
        {
            // 创建一个DES 算法的实例。自动产生Key
            System.Security.Cryptography.AesManaged desCrypto = new System.Security.Cryptography.AesManaged();

            // 返回自动创建的Key 用于加密
            return utf8.GetString(desCrypto.Key, 0, desCrypto.Key.Length);
        }

        /**/
        /// <summary>
        /// 加密字符串
        /// </summary>
        /// <param name="sInputString">输入字符</param>
        /// <param name="sKey">Key</param>
        /// <returns>加密结果</returns>
        public string EncryptString(string sInputString, string sKey)
        {
            byte[] data = Encoding.UTF8.GetBytes(sInputString);
            byte[] result;
            System.Security.Cryptography.AesManaged DES = new System.Security.Cryptography.AesManaged();
            DES.Key = UTF8Encoding.UTF8.GetBytes(sKey);
            DES.IV = UTF8Encoding.UTF8.GetBytes(sKey);
            ICryptoTransform desencrypt = DES.CreateEncryptor();
            result = desencrypt.TransformFinalBlock(data, 0, data.Length);

            string desString = "";
            for (int i = 0; i < result.Length; i++)
            {
                desString += result[i].ToString() + "-";
            }

            //return desString.TrimEnd('-');
            return BitConverter.ToString(result);
        }

        /**/
        /// <summary>
        /// 解密字符串
        /// </summary>
        /// <param name="sInputString">输入字符</param>
        /// <param name="sKey">Key</param>
        /// <returns>解密结果</returns>
        public string DecryptString(string sInputString, string sKey)
        {
            string[] sInput = sInputString.Split("-".ToCharArray());
            byte[] data = new byte[sInput.Length];
            byte[] result;
            for (int i = 0; i < sInput.Length; i++)
                data[i] = byte.Parse(sInput[i], System.Globalization.NumberStyles.HexNumber);

            System.Security.Cryptography.AesManaged DES = new System.Security.Cryptography.AesManaged();
            DES.Key = UTF8Encoding.UTF8.GetBytes(sKey);
            DES.IV = UTF8Encoding.UTF8.GetBytes(sKey);
            ICryptoTransform desencrypt = DES.CreateDecryptor();
            result = desencrypt.TransformFinalBlock(data, 0, data.Length);
            return utf8.GetString(result, 0, result.Length);
        }

        /**/
        /// <summary>
        /// 加密文件
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <param name="sOutputFilename">输出文件</param>
        /// <param name="sKey">Key</param>
        public void EncryptFile(string sInputFilename,
          string sOutputFilename,
          string sKey)
        {
            FileStream fsInput = new FileStream(sInputFilename,
              FileMode.Open,
              FileAccess.Read);

            FileStream fsEncrypted = new FileStream(sOutputFilename,
              FileMode.Create,
              FileAccess.Write);
            System.Security.Cryptography.AesManaged DES = new System.Security.Cryptography.AesManaged();
            DES.Key = UTF8Encoding.UTF8.GetBytes(sKey);
            DES.IV = UTF8Encoding.UTF8.GetBytes(sKey);
            ICryptoTransform desencrypt = DES.CreateEncryptor();
            CryptoStream cryptostream = new CryptoStream(fsEncrypted,
              desencrypt,
              CryptoStreamMode.Write);

            byte[] bytearrayinput = new byte[fsInput.Length];
            fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
            cryptostream.Close();
            fsInput.Close();
            fsEncrypted.Close();
        }

        /**/
        /// <summary>
        /// 解密文件
        /// </summary>
        /// <param name="sInputFilename">输入文件</param>
        /// <param name="sOutputFilename">输出文件</param>
        /// <param name="sKey">Key</param>
        public void DecryptFile(string sInputFilename,
          string sOutputFilename,
          string sKey)
        {
            System.Security.Cryptography.AesManaged DES = new System.Security.Cryptography.AesManaged();
            DES.Key = UTF8Encoding.UTF8.GetBytes(sKey);
            DES.IV = UTF8Encoding.UTF8.GetBytes(sKey);

            FileStream fsread = new FileStream(sInputFilename,
              FileMode.Open,
              FileAccess.Read);
            ICryptoTransform desdecrypt = DES.CreateDecryptor();
            CryptoStream cryptostreamDecr = new CryptoStream(fsread,
              desdecrypt,
              CryptoStreamMode.Read);
            StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
            fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
            fsDecrypted.Flush();
            fsDecrypted.Close();
        }

    }
}
